package org.summerframework.core.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 石超
 * @version v1.0.0
 */
public class AnnotationHelper {

    private static final AnnotationHelper helper = new AnnotationHelper();

    protected AnnotationHelper() {

    }

    public static AnnotationHelper getInstance() {
        return helper;
    }

    /**
     * 得到类上面的注解信息
     *
     * @param scannerClass
     * @param allowInjectClass
     * @return
     */
    public <T extends Annotation> T getClassAnnotation(Class<?> scannerClass, Class<T> allowInjectClass) {

        if (!scannerClass.isAnnotationPresent(allowInjectClass)) {
            return null;
        }

        return scannerClass.getAnnotation(allowInjectClass);
    }

    /**
     * 等到方法级别注解的信息
     *
     * @param scannerClass：需要被扫描的class文件
     * @param allowInjectClass：注解的文件
     * @return
     */
    public <T extends Annotation> List<T> getMethodAnnotation(Class<?> scannerClass, Class<T> allowInjectClass) {
        List<T> annotations = new ArrayList<>();

        for (Method method : scannerClass.getDeclaredMethods()) {
            if (!method.isAnnotationPresent(allowInjectClass)) {
                continue;
            }

            annotations.add(method.getAnnotation(allowInjectClass));
        }

        return annotations;
    }

    /**
     * 等到方法级别注解的信息
     *
     * @param scannerClass：需要被扫描的class文件
     * @param allowInjectClass：注解的文件
     * @return
     */
    public <T extends Annotation> List<Method> getMethod(Class<?> scannerClass, Class<T> allowInjectClass) {
        List<Method> annotations = new ArrayList<>();

        for (Method method : scannerClass.getDeclaredMethods()) {
            if (!method.isAnnotationPresent(allowInjectClass)) {
                continue;
            }

            annotations.add(method);
        }

        return annotations;
    }

    /**
     * 使用Java反射得到注解的信息
     *
     * @param annotation
     * @param methodName
     * @return
     * @throws NoSuchMethodException
     * @throws SecurityException
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     * @throws InvocationTargetException
     */
    public Object getAnnotationInfo(Annotation annotation, String methodName) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        if (annotation == null) {
            return null;
        }

        Method method = annotation.getClass().getDeclaredMethod(methodName);
        return method.invoke(annotation);
    }
}
